package cn.com.joyplus.wechat.controller;

import cn.com.joyplus.wechat.listener.IMsgListener;
import cn.com.joyplus.wechat.model.WechatContext;
import cn.com.joyplus.wechat.model.WechatEvent;
import cn.com.joyplus.wechat.model.WxMsgCache;
import cn.com.joyplus.wechat.service.WechatCoreApiService;
import cn.com.joyplus.wechat.utils.StringUtils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.nio.charset.StandardCharsets;

/**
 * Created by 王灏川(wangrs@qq.com) on 2017/8/11 0011.
 */
@Controller
@RequestMapping(value = "wx-event-dispatcher", produces = "text/plain;charset=UTF-8")
public class WxEventDispatcherController {
    private static final Logger logger = LoggerFactory.getLogger(WxEventDispatcherController.class);


    @Autowired
    WechatCoreApiService wechatCoreApiService;


    @Autowired
    WxMsgCache wxMsgCache;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    WechatContext wechatContext;

    @RequestMapping("/listener")
    @ResponseBody
    public String msgListener(HttpServletRequest request) {
        final String defaultSuccseeMsg = "success";
        final String defaultFailedMsg = "failed";

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        String openId = request.getParameter("openId");
        String encryptType = request.getParameter("encrypt_type");
        String msgSignature = request.getParameter("msg_signature");

        logger.debug(String.format("signature:%s,timestamp:%s,nonce:%s,echostr:%s,openId:%s,encryptType:%s,msgSignature:%s",
                signature, timestamp, nonce, echostr, openId, encryptType, msgSignature));

        if (null != signature && null != timestamp && null != nonce && null != echostr) {
            logger.info("Init wechat incoming...");
            return (wechatCoreApiService.checkSignature(signature, timestamp, nonce)) ? echostr : null;
        } else {
            BufferedReader reqReader = null;
            try {
                reqReader = request.getReader();
                char[] buf = new char[1024];
                int len = 0;
                StringBuffer msg = new StringBuffer();
                while ((len = reqReader.read(buf)) != -1) msg.append(buf, 0, len);

                String wxMsg = msg.toString();

                ObjectMapper objectMapper = new XmlMapper();

                objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

                WechatEvent event = objectMapper.readValue(wxMsg.getBytes(StandardCharsets.UTF_8), WechatEvent.class);

                if (null != event.getEncrypt()) {
                    wxMsg = wechatCoreApiService.DecryptMsg(msgSignature, timestamp, nonce, wxMsg);
                    event = objectMapper.readValue(wxMsg.getBytes(StandardCharsets.UTF_8), WechatEvent.class);
                }

                if (null != event && null != event.getEvent() && null != event.getMsgType()) {
                    logger.info("Receive wechat msg:" + wxMsg);
                    if (null != event.getMsgId()) {
                        //防止重复处理消息，已经处理过的消息直接跳过。
                        if (null != wxMsgCache.getMsgIdFromCache(event.getMsgId())) {
                            return defaultSuccseeMsg;
                        } else {
                            wxMsgCache.putMsgIdToCache(event.getMsgId());
                        }
                    }

                    if (null == wechatContext.getMyOpenId() && null != event.getToUserName()) {
                        wechatContext.setMyOpenId(event.getToUserName());
                    }

                    event.setStrVal(wxMsg);


                    String listenerBeanName = String.format("%s%sListener", event.getMsgType().toLowerCase(),
                            StringUtils.upperFirstCase(event.getEvent().toLowerCase()));

                    if (applicationContext.containsBean(listenerBeanName)) {
                        logger.info(String.format("Invoker %s", listenerBeanName));
                        String result = ((IMsgListener) applicationContext.getBean(listenerBeanName)).process(event);
                        logger.debug(String.format("Invoker Result:\n %s", result));
                        return result;
                    } else {
                        logger.warn(String.format("Listener process bean:%s not be found!", listenerBeanName));
                        return defaultFailedMsg;
                    }
                }
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
                return defaultFailedMsg;
            }
            return defaultSuccseeMsg;
        }
    }




}
